﻿/*
* ========================================================================
* 类说明：
*   提供给 通用软件 调用的封装对象
* 
* 作者：HGS   时间：2024/11/4 13:29:54
* 
* 修改者：         时间：           
* 修改说明：
* ========================================================================
*/

using GZHJ.Tool;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using VM.Shared.Model;
using VM.Shared.ReturnValue;

namespace MESLib
{
    public class MES
    {
        /// <summary>
        /// 绑定蓝牙Mac地址
        /// </summary>
        /// <param name="mesUrl"></param>
        /// <param name="sn"></param>
        /// <param name="testInfo"></param>
        /// <param name="devInfo"></param>
        /// <returns></returns>
        public ReturnError Bind(string mesUrl, string sn, TestInfo testInfo, DevInfo devInfo)
        {
            if (null == testInfo.DicTestResult)
            {
                return new ReturnError() { IsOK = false, ErrStr = "测试信息不能为空" };
            }

            string 蓝牙Mac = string.Empty;
            var ret = testInfo.DicTestResult.Where(obj => obj.Key.Contains("蓝牙Mac"));
            if (ret != null && ret.Count() > 0)
            {
                蓝牙Mac = ret.FirstOrDefault().Value.TestValue ?? "";
            }
            ReturnError mesReturn = MesHelper.SnBindMAC(sn, 蓝牙Mac, mesUrl, devInfo.FactoryId);

            return mesReturn;

        }
        /// <summary>
        /// SN校验
        /// </summary>
        /// <param name="mesUrl"></param>
        /// <param name="sn"></param>
        /// <param name="devInfo"></param>
        /// <returns></returns>
        public ReturnError SNCheck(string mesUrl, string sn, DevInfo devInfo)
        {
            ReturnError mesReturn = MesHelper.QuerySN(sn, devInfo.DeviceCode, devInfo.Business, mesUrl, devInfo.FactoryId);

            return mesReturn;
        }
        /// <summary>
        /// SN校验
        /// </summary>
        /// <param name="mesUrl"></param>
        /// <param name="snList"></param>
        /// <param name="devInfo"></param>
        /// <returns></returns>
        public ReturnError SNCheck(string mesUrl, List<string> snList, DevInfo devInfo)
        {
            ReturnError mesReturn = MesHelper.QuerySN(snList, devInfo.DeviceCode, devInfo.Business, mesUrl, devInfo.FactoryId);

            return mesReturn;
        }
        /// <summary>
        /// 录入过站信息
        /// </summary>
        /// <param name="mesUrl"></param>
        /// <param name="sn"></param>
        /// <param name="testInfo"></param>
        /// <param name="devInfo"></param>
        /// <returns></returns>
        public ReturnError UploadData(string mesUrl, string sn, TestInfo testInfo, DevInfo devInfo)
        {
            string statu = testInfo.IsOK ? "Y" : "N";
            List<badcode> badList = new List<badcode>();
            if (statu == "N")
            {
                badList.Add(new badcode()
                {
                    badCode = GetBadCodeFromBusiness(devInfo.Business),
                    badPosition = "测试出现NG项，详情请查看测试报告",
                });
            }
            ReturnError mesReturn = MesHelper.Insert(sn, statu, badList, devInfo.Business, mesUrl, devInfo.FactoryId, devInfo.DeviceCode, testInfo.FilePath);
            //var ss = testInfo.DicTestResult.First(item => item.Key.Contains("蓝牙Mac"));
            return mesReturn;
        }
        /// <summary>
        /// 录入过站信息
        /// </summary>
        /// <param name="mesUrl"></param>
        /// <param name="sn"></param>
        /// <param name="testInfo"></param>
        /// <param name="devInfo"></param>
        /// <returns></returns>
        public ReturnError UploadData(string mesUrl, List<string> snList, TestInfo testInfo, DevInfo devInfo)
        {
            string statu = testInfo.IsOK ? "Y" : "N";
            List<badcode> badList = new List<badcode>();
            if (statu == "N")
            {
                badList.Add(new badcode()
                {
                    badCode = GetBadCodeFromBusiness(devInfo.Business),
                    badPosition = "测试出现NG项，详情请查看测试报告",
                });
            }
            ReturnError mesReturn = MesHelper.Insert(snList, statu, badList, devInfo.Business, mesUrl, devInfo.FactoryId, devInfo.DeviceCode, testInfo.FilePath);
            return mesReturn;
        }
        /// <summary>
        /// 采集测试项数据
        /// </summary>
        /// <param name="mesUrl"></param>
        /// <param name="snList"></param>
        /// <param name="testInfo"></param>
        /// <param name="devInfo"></param>
        /// <returns></returns>
        public ReturnError CollectData(string mesUrl, List<string> snList, TestInfo testInfo, DevInfo devInfo)
        {
            if (snList == null || snList.Count <= 0)
            {
                return new ReturnError() { IsOK = false, ErrStr = "传递SN不能为空！" };
            }

            var parameter = new InputCollectTestDataRequest();
            parameter.Business = devInfo.Business;
            parameter.DeviceCode = devInfo.DeviceCode;

            //sn赋值，兼容FCT双码的情况
            if (snList.Count == 1)
            {
                parameter.SN = snList[0];
            }
            else
            {
                parameter.SN = string.Join("_", snList);
                if (parameter.SN.EndsWith("_"))
                {
                    parameter.SN = parameter.SN.Substring(0, parameter.SN.Length - 1);
                }
            }

            parameter.FinishTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            parameter.Result = testInfo.IsOK ? "Y" : "N";
            parameter.data = GetCollectTestData(testInfo, out string 错误信息);
            if (parameter.data.Count() <= 0)
            {
                return new ReturnError() { IsOK = false, ErrStr = $"未获取到采集测试项数据，{错误信息}" };
            }

            ReturnError mesReturn = MesHelper.InputCollectTestData(parameter, devInfo.FactoryId, mesUrl);
            return mesReturn;
        }




        //=================================== 辅助方法 =====================================
        /// <summary>
        /// 根据工序编号，获取对应不良编码描述
        /// </summary>
        /// <param name="business"></param>
        /// <returns></returns>
        private string GetBadCodeFromBusiness(string business)
        {
            switch (business.ToUpper())
            {
                case "OP120": return "高温老化不良";
                case "OP130": return "高低温老化不良";
                case "OP140": return "震动测试不良";
                case "OP150": return "综合测试不良";
                case "OP160": return "成品测试不良";
                case "OP170": return "触屏测试不良";
                case "OP180": return "支架打钉不良";
                case "OP190": return "GP12测试不良";
                case "OP200": return "恢复出厂不良";
                default: break;
            }
            return "";
        }
        /// <summary>
        /// 获取需要上传的采集测试项数据
        /// </summary>
        /// <param name="testInfo"></param>
        /// <returns></returns>
        private List<string> GetCollectTestData(TestInfo testInfo, out string 错误信息)
        {
            错误信息 = string.Empty;
            try
            {
                //读取配置文件，获取需要上传的测试项Key，配置文件数据格式如下，按行分割，数据格式如下：
                //通用软件中测试项名称|要替换写入到MES中的名称
                //通用软件中测试项名称|要替换写入到MES中的名称
                //...

                //读配置文件
                string dllPath = Assembly.GetExecutingAssembly().Location;
                string configPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(dllPath), "CollectTestDataConfig.ini");
                var 行数据列表 = ReadAllLineContent(configPath, out 错误信息);
                if (行数据列表.Count() <= 0)
                {
                    错误信息 = "采集测试项数据配置文件行内容为空！";
                    return new List<string>();
                }

                //获取需要采集上传测试项数据
                List<string> 结果列表 = new List<string>();
                foreach (var 行内容 in 行数据列表)
                {
                    string[] strArray = 行内容.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                    if (strArray.Length < 2)
                    {
                        LogHelper.Warn($"[MES.GetCollectTestData]获取需要上传的采集测试项数据过程出现警告项，行内容数据格式不对，行内容：{行内容}");
                        continue;  //数据格式不匹配
                    }

                    string 测试项键名称 = strArray[0];
                    string 替换键名称 = strArray[1];
                    var 键值 = GetTestValueByKey(测试项键名称, testInfo);
                    if (string.IsNullOrWhiteSpace(键值))
                    {
                        LogHelper.Error($"[MES.GetCollectTestData]获取需要上传的采集测试项数据过程出现警告项，键值为空，行内容：{行内容}");
                        错误信息 = $"[{测试项键名称}]测试值为空！";
                        return new List<string>();  //不允许出现空的测试项值
                    }

                    结果列表.Add($"{替换键名称}:{键值}");
                }

                return 结果列表;
            }
            catch (Exception ex)
            {
                错误信息 = ex.Message;
                LogHelper.Error($"[MES.GetCollectTestData]异常，{ex.Message}，{ex.StackTrace}");
            }

            return new List<string>();
        }
        /// <summary>
        /// 读取指定文件所有行数据
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="错误信息"></param>
        /// <returns></returns>
        private List<string> ReadAllLineContent(string filePath, out string 错误信息)
        {
            错误信息 = string.Empty;
            if (!System.IO.File.Exists(filePath))
            {
                错误信息 = $"采集测试项数据配置文件不存在！{filePath}";
                return new List<string>();
            }
            //读取配置文件所有行数据
            string readContent = "";
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                byte[] bt = new byte[fs.Length];
                fs.Read(bt, 0, bt.Length);
                readContent = Encoding.UTF8.GetString(bt);
                fs.Close();
            }
            if (string.IsNullOrWhiteSpace(readContent))
            {
                错误信息 = "采集测试项数据配置文件内容为空！";
                return new List<string>();
            }
            string[] strArray = readContent.Replace("\r\n", "\n")
                                           .Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
            List<string> list = new List<string>();
            foreach (var lineContent in strArray)
            {
                if (lineContent.StartsWith("#"))
                    continue;  //过滤注释内容

                list.Add(lineContent);
            }
            return list;
        }
        /// <summary>
        /// 获取指定键对应测试项的测试值
        /// </summary>
        /// <param name="键值"></param>
        /// <param name="testInfo"></param>
        /// <returns></returns>
        private string GetTestValueByKey(string 键值, TestInfo testInfo)
        {
            try
            {
                var ret = testInfo.DicTestResult.Where(obj => obj.Value.TestItemName.Contains(键值));
                if (ret != null && ret.Count() > 0)
                {
                    return ret.FirstOrDefault().Value.TestValue;
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error($"MES.GetTestValueByKey]异常，{ex.Message}，{ex.StackTrace}");
            }
            return string.Empty;
        }
    }
}
